///////////////////////////////////////////
// Authors : Mathieu Robitaille - 6396682
//           Sacha Sukhdeo - 6054412
// Class : COMP445
//         Assignment 2
///////////////////////////////////////////

#pragma once

#include <winsock.h>
#include "packet.h"
#include <string>
#include <fstream>
#include <vector> 

#pragma comment(lib, "ws2_32.lib")

class TcpBase {
public:
    TcpBase() : localSeqNb(0), remoteSeqNb(0) {}
    virtual ~TcpBase() {}
    virtual int msg_recv(SOCKET s,Msg * msg, SOCKADDR* p_from = NULL);
    virtual int msg_send(SOCKET s,Msg * msg, SOCKADDR* p_addr, int addrSize);
    int WaitForSocket(FD_SET fds, LPTIMEVAL timeout);
    unsigned long ResolveName(char name[]);
    static void err_sys(char * fmt,...);
    void SendFile(const std::string& filename, SOCKET sTo, SOCKET sFrom, const std::string& hostname, SOCKADDR* p_addr, int addrSize);
    void ReceiveFile(const std::string& filename, SOCKET sTo, SOCKET sFrom, SOCKADDR * addrFrom, const std::string& hostname);
    void SendFileList(std::string directory, SOCKET sTo, SOCKET sFrom, SOCKADDR* p_addr, int addrSize);
    void ReceiveFileList(SOCKET sTo, SOCKET sFrom, SOCKADDR* addrFrom);
    void Log(char * fmt,...);
    virtual std::string LogFile() const = 0;
	int NACKMsgIndex;
	std::vector<Msg> msgBuffer;
	bool nackReceived;

protected:
    char m_hostname[HOSTNAME_LENGTH];
    int localSeqNb;
    int remoteSeqNb;

    typedef struct {
        int bytes;
        int packets;
        int effectiveBytes;
        int effectivePackets;
    } LogInfo;

    void SendPacket(SOCKET sTo, SOCKET sFrom, Msg m, SOCKADDR* p_addr, int addrSize, LogInfo& li, bool isLast = false);
    Msg ReceivePacket(SOCKET sFrom, SOCKET sTo,SOCKADDR * addrFrom, LogInfo& li);
    static TIMEVAL TIMEOUT;
private:
    std::ofstream m_log;
    static const int WINDOW_SIZE;
    static const int SEQ_NB_RANGE;
    static const int LAST_PACKET_MAX_RESEND;
};
